#include "SRVConnection.h"
#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>
#include <iterator>
#include <utility>
#include "SingletonHolder.h"


SRVConnection::SRVConnection(boost::asio::io_service &io_service,std::queue<boost::shared_ptr<Data> > *theReceived) : myStrand(io_service) 
																													  /*mySocket(io_service)*/
																							
{
	mySocket = new boost::asio::ip::tcp::socket(io_service);
	myReceived = theReceived;
	myReceiving = false;
}


boost::asio::ip::tcp::socket& SRVConnection::GetSocket()
{
	return (*mySocket);
}


void SRVConnection::Start()
{
	mySocket->async_receive(boost::asio::buffer(myLocalBuffer),myStrand.wrap(boost::bind(&SRVConnection::handle_read,shared_from_this(),
																					boost::asio::placeholders::error,
																				    boost::asio::placeholders::bytes_transferred)));
}

/*
void SRVConnection::handle_read(const boost::system::error_code &er, std::size_t bytes_transfered)
{
	if(er)
		return;

	try
	{
		std::vector<byte> received(myBuffer.data(),myBuffer.data() + bytes_transfered);

		if(myRequest.Parse(received))
		{
			DataContainer *aContainer = new DataContainer();
			aContainer->Parse(received);
			boost::mutex::scoped_lock lock(myMutex);
			myReceived->push((*aContainer));
		}
	}
	catch (std::exception &ex)
	{
		SingletonHolder::Instance().WriteEx(ex.what());
	}

	mySocket.async_receive(boost::asio::buffer(myBuffer),myStrand.wrap(boost::bind(&SRVConnection::handle_read,shared_from_this(),
		boost::asio::placeholders::error,
		boost::asio::placeholders::bytes_transferred)));
}
*/

void SRVConnection::handle_read(const boost::system::error_code &er, std::size_t bytes_transfered)
{
	if(er)
	{
		if(myRequest.Parse(myOveralBuffer))
		{
			//boost::shared_ptr<PComunicator::DataContainer> aContainer(new PComunicator::DataContainer());
			//aContainer->Parse(myOveralBuffer);
			boost::shared_ptr<Data> aSharedData(new Data());
			aSharedData->theContainer = myRequest;
			aSharedData->theConnection = mySocket;

			boost::mutex::scoped_lock lock(myMutex);
			myReceived->push(aSharedData);

			SingletonHolder::Instance().WriteMsg("Stuff received ok");
			
			myReceiving = false;
			myOveralBuffer.clear();
		}
		else
		{
			SingletonHolder::Instance().WriteEx(er.message());
		}
		return;
	}

	if(!myReceiving)
	{
		try
		{

			std::string received_size(myLocalBuffer.data(),myLocalBuffer.data() + bytes_transfered);
			myReceivingSize = boost::lexical_cast<std::size_t>(received_size);

			myReceiving = true;
		}
		catch(...)
		{
			myReceiving = false;
			SingletonHolder::Instance().WriteEx("Mishmashed data received");
			return;
		}
		
	}
	else
	{
		std::vector<unsigned char> received(myLocalBuffer.data(),myLocalBuffer.data() + bytes_transfered);
		std::copy(received.begin(),received.end(),std::back_inserter(myOveralBuffer));

		myReceivingSize -= bytes_transfered;

		if(myReceivingSize == 0)
		{
			myReceiving = false;
			
			try
			{
				if(myRequest.Parse(myOveralBuffer))
				{
					//boost::shared_ptr<PComunicator::DataContainer> aContainer(new PComunicator::DataContainer());
					//aContainer->Parse(myOveralBuffer);
					boost::shared_ptr<Data> aSharedData(new Data());
					aSharedData->theContainer = myRequest;
					aSharedData->theConnection = mySocket;

					boost::mutex::scoped_lock lock(myMutex);
					myReceived->push(aSharedData);
					
					SingletonHolder::Instance().WriteMsg("Stuff received ok");

					myReceiving = false;
					myOveralBuffer.clear();

					return;
				}
			}
			catch (std::exception &ex)
			{
				SingletonHolder::Instance().WriteEx(ex.what());
			}
		}

	}	

	mySocket->async_receive(boost::asio::buffer(myLocalBuffer),myStrand.wrap(boost::bind(&SRVConnection::handle_read,shared_from_this(),
		boost::asio::placeholders::error,
		boost::asio::placeholders::bytes_transferred)));
}


void SRVConnection::handle_write(const boost::system::error_code &er)
{
	if(!er)
	{
		boost::system::error_code ignored;
		mySocket->shutdown(boost::asio::ip::tcp::socket::shutdown_both,ignored);
	}
}

